package io.github.bluesbruce.server;

import io.github.bluesbruce.commons.Constant;
import io.github.bluesbruce.commons.TransferFile;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Netty服务端处理程序
 *
 * @author BBF
 */
public class DolphinServerHandler extends ChannelInboundHandlerAdapter {

  private static final Logger LOGGER = LoggerFactory.getLogger(DolphinServerHandler.class);
  private static final String PATH = "d:\\temp2";

  @Override
  public void channelActive(ChannelHandlerContext ctx) {
    if (LOGGER.isDebugEnabled()) {
      InetSocketAddress remote = (InetSocketAddress) ctx.channel().remoteAddress();
      LOGGER.debug("====建立连接，IP={}，port={}",
          remote.getAddress().getHostAddress(), remote.getPort());
    }
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) {
    if (LOGGER.isDebugEnabled()) {
      InetSocketAddress remote = (InetSocketAddress) ctx.channel().remoteAddress();
      LOGGER.debug("====断开连接，IP={}，port={}",
          remote.getAddress().getHostAddress(), remote.getPort());
    }
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (msg instanceof String) {

      ctx.writeAndFlush(Constant.TRANSMIT_START);
      // 秒传功能还没有开发出来
//      ctx.writeAndFlush(Constant.TRANSMIT_MD5_EXISTS);
//      LOGGER.info("秒传文件：md5 = {}", msg);
    } else if (msg instanceof TransferFile) {
      TransferFile file = (TransferFile) msg;
      int start = file.getStarPos();
      int byteRead = file.getEndPos();
      byte[] bytes = file.getBytes();
      Path path = Paths.get(PATH, file.getMd5() + file.getExt());
      // 以读写方式创建文件
      RandomAccessFile randomAccessFile = new RandomAccessFile(path.toFile(), Constant.FILE_WRITE);
      randomAccessFile.seek(start);
      randomAccessFile.write(bytes);
      if (byteRead > 0) {
        // 将下一段的起始点发给客户端
        ctx.writeAndFlush(start + byteRead).addListener(new ChannelFutureListener() {
          @Override
          public void operationComplete(ChannelFuture future) throws Exception {
            randomAccessFile.close();
            if (Constant.SEND_SIZE != byteRead) {
              // 当读的字节数小于单次发送数量，表示文件已全接收
              future.channel().close();
              if (LOGGER.isDebugEnabled()) {
                InetSocketAddress remote = (InetSocketAddress) ctx.channel().remoteAddress();
                LOGGER.debug("====文件接收完毕，IP={}，port={}，保存文件={}",
                    remote.getAddress().getHostAddress(), remote.getPort(), path.toString());
              }
            }
          }
        });
      } else {
        ctx.close();
      }
    } else {
      ctx.channel().writeAndFlush(Constant.SEND_CORRECT_DATA)
          .addListener(ChannelFutureListener.CLOSE);
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    ctx.close();
    cause.printStackTrace();
  }
}
